package com.autumn.platform.dao;

import java.lang.reflect.Field;

import org.apache.ibatis.executor.CachingExecutor;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.AutoMappingBehavior;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.transaction.Transaction;

import com.autumn.platform.dao.binding.MapperRegistry;
import com.autumn.platform.dao.schema.SchemaXMLLanguageDriver;
import com.autumn.platform.dao.schema.executor.BatchExecutor;
import com.autumn.platform.dao.schema.executor.ReuseExecutor;
import com.autumn.platform.dao.schema.executor.SimpleExecutor;

public class Configuration extends org.apache.ibatis.session.Configuration {

    protected MapperRegistry mapperRegistry = new MapperRegistry(this);

    public Configuration() {
        super();
        customConfiguration();
    }

    public Configuration(Environment environment) {
        super(environment);
        customConfiguration();
    }

    /**
     * 自定义配置
     */
    private void customConfiguration() {
        try {
            // 替换默认的MapperRegistry
            Field field = org.apache.ibatis.session.Configuration.class.getDeclaredField("mapperRegistry");
            if (!field.isAccessible()) {
                field.setAccessible(true);
            }

            field.set(this, new MapperRegistry(this));
            defaultConfig();
        } catch (Exception e) {
            //ignore
            //e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 自动配置
     */
    protected void defaultConfig() {
        this.setMapUnderscoreToCamelCase(true); //Java属性与数据库字段采用驼峰式对应
        this.setAutoMappingBehavior(AutoMappingBehavior.FULL);//字段映射采用复合规则，有配置的使用配置映射，未配置的采用默认映射 
        this.setSafeResultHandlerEnabled(false);
        this.setCallSettersOnNulls(true);
        this.setUseColumnLabel(true);
        this.setLogPrefix("mybatis.");
        this.setDefaultScriptingLanguage(SchemaXMLLanguageDriver.class);
    }

    /**
     * 覆盖执行器的创建，从而覆盖缓存键值CacheKey的生成，以避免在生成缓存键值时，由于含有表达式而出现异常
     */
    @Override
    public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
        executorType = executorType == null ? defaultExecutorType : executorType;
        executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
        Executor executor;
        if (ExecutorType.BATCH == executorType) {
            executor = new BatchExecutor(this, transaction);
        } else if (ExecutorType.REUSE == executorType) {
            executor = new ReuseExecutor(this, transaction);
        } else {
            executor = new SimpleExecutor(this, transaction);
        }
        if (cacheEnabled) {
            executor = new CachingExecutor(executor);
        }
        executor = (Executor) interceptorChain.pluginAll(executor);
        return executor;
    }
}
